---
type: integration
title: '@astrojs/db'
description: Astro 프로젝트에서 @astrojs/db 통합을 사용하는 방법을 알아보세요.
sidebar:
  label: DB
githubIntegrationURL: 'https://github.com/withastro/astro/tree/main/packages/db/'
category: other
i18nReady: true
---
import { FileTree } from '@astrojs/starlight/components';
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro';
import ReadMore from '~/components/ReadMore.astro';
import Since from '~/components/Since.astro';

Astro DB는 Astro 생태계를 위해 설계된 완전 관리형 SQL 데이터베이스입니다. Astro에서 로컬로 개발하고 모든 [libSQL 호환 데이터베이스](/ko/guides/astro-db/)에 배포하세요.

Astro DB를 사용하면 콘텐츠를 관계형 데이터베이스로 쿼리하고 모델링할 수 있는 강력하고 타입 안정성을 갖춘 로컬에서 동작하는 도구를 갖게 됩니다.

<ReadMore>전체 사용법과 예시는 [Astro DB 가이드](/ko/guides/astro-db/)를 참조하세요.</ReadMore>

## 설치

Astro에는 공식 통합 설정을 자동화하는 `astro add` 명령이 포함되어 있습니다. 원하는 경우 대신 [통합을 수동으로 설치](#수동-설치)할 수 있습니다.

새 터미널 창에서 다음 명령 중 하나를 실행합니다.

<PackageManagerTabs>
  <Fragment slot="npm">
  ```sh
  npx astro add db
    ```
  </Fragment>
  <Fragment slot="pnpm">
  ```sh
  pnpm astro add db
  ```
  </Fragment>
  <Fragment slot="yarn">
  ```sh
  yarn astro add db
  ```
  </Fragment>
 </PackageManagerTabs>

#### 수동 설치

처음부터 직접 설정하려면 `astro add`를 건너뛰고 다음 지침에 따라 Astro DB를 직접 설치하세요.

##### 1. 패키지 관리자를 통해 npm에서 통합 설치

   <PackageManagerTabs>
     <Fragment slot="npm">
     ```shell
     npm install @astrojs/db
     ```
     </Fragment>
     <Fragment slot="pnpm">
     ```shell
     pnpm add @astrojs/db
     ```
     </Fragment>
     <Fragment slot="yarn">
     ```shell
     yarn add @astrojs/db
     ```
     </Fragment>
   </PackageManagerTabs>

##### 2. `astro.config.mjs` 파일에 통합 추가

    ```js title="astro.config.mjs" ins={2,6}
    import { defineConfig } from 'astro/config';
    import db from '@astrojs/db';

    export default defineConfig({
      integrations: [
       db()
      ]
    });
    ```

##### 3. 데이터베이스 구성

프로젝트 루트에 `db/config.ts` 파일을 생성합니다. 이 파일은 Astro가 자동으로 로드하여 데이터베이스 테이블을 구성하는 데 사용되는 특수 파일입니다.

```ts
// db/config.ts
import { defineDb } from 'astro:db';

export default defineDb({
  tables: {},
})
```

## 구성

### `mode`

<p>

**타입:** `'node' | 'web'`<br />
**기본값:** `'node'`<br />
<Since v="0.18.0" pkg="@astrojs/db" />
</p>

프로덕션 환경에서 데이터베이스에 연결할 때 사용할 드라이버를 구성합니다.

기본적으로 Astro DB는 프로덕션 배포에 Node.js 기반 libSQL 드라이버를 사용합니다. Node.js 런타임을 사용하는 대부분의 Astro 호스팅 또는 자체 호스팅 웹사이트에는 `node` 드라이버 모드로 충분합니다. 이를 통해 `memory:`, `file:`, `ws:`, `wss:`, `libsql`, `http`, `https` 등 여러 프로토콜을 통해 데이터베이스에 연결할 수 있으며, [임베디드 레플리카](/ko/guides/astro-db/#syncurl)와 같은 고급 기능도 사용할 수 있습니다.

Cloudflare Workers나 Deno와 같은 Node.js가 아닌 런타임의 서버리스 환경에 배포할 경우, 웹 기반 libSQL 드라이버를 사용할 수 있습니다. `web` 모드를 사용하여 배포할 경우, `libsql`, `http`, `https`를 통해 웹 기반 연결을 설정할 수 있습니다.

Node.js 환경이 아닌 경우 웹 libSQL 드라이버 모드를 사용하려면 어댑터 구성에서 `mode` 속성을 설정해야 합니다.

```ts title="astro.config.mjs" ins={7}
import { defineConfig } from 'astro/config';
import db from '@astrojs/db';

export default defineConfig({
  integrations: [
   db({
     mode: 'web'
   })
  ]
});
```

## 테이블 구성 참조

### `columns`

<p>

**타입:** `ColumnsConfig`
</p>

테이블 열은 `columns` 객체를 사용하여 구성됩니다.

```ts
import { defineTable, column, NOW } from 'astro:db';

const Comment = defineTable({
	columns: {
		id: column.number({ primaryKey: true }),
		author: column.text(),
		content: column.text({ optional: true }),
		published: column.date({ default: NOW }),
	},
});
```

열은 `column` 유틸리티를 사용하여 구성됩니다. `column`은 다음 타입을 지원합니다:

- **`column.text(...)`** - 일반 또는 서식 있는 텍스트 콘텐츠 저장
- **`column.number(...)`** - 정수 및 부동 소수점 값 저장
- **`column.boolean(...)`** - 참/거짓 값 저장
- **`column.date(...)`** - 데이터 저장을 위해 ISO 문자열로 구문 분석된 `Date` 객체를 저장
- **`column.json(...)`** - 데이터 저장을 위해 문자열로 구문 분석된 임의의 JSON Blob을 저장

모든 열에는 몇 가지 공유 구성 값이 있습니다.

- `primaryKey` - `number` 또는 `text` 열을 고유 식별자로 설정합니다.
- `optional` - Astro DB는 기본적으로 모든 열에 `NOT NULL`을 사용합니다. null 값을 허용하려면 `optional`을 `true`로 설정하세요.
- `default` - 새로 삽입된 항목의 기본값을 설정합니다. 이는 에 대해 정적 값이나 타임스탬프와 같이 생성된 값을 나타내는 `sql` 문자열을 허용합니다.
- `unique` - 열을 고유한 것으로 표시합니다. 이렇게 하면 테이블의 항목 전체에서 값이 중복되는 것을 방지할 수 있습니다.
- `references` - 각 열과 관련된 테이블을 참조합니다. 이는 외래 키 제약 조건을 설정합니다. 즉, 각 열 값은 참조된 테이블에서 일치하는 값을 가져야 합니다.

`text` 열은 문자열 리터럴 목록을 선택적으로 정의하여 타입 생성을 위한 열거형의 역할을 수행할 수 있습니다. 그러나 **런타임 유효성 검사는 수행되지 않습니다.** 값 제거, 추가 및 변경은 프로젝트 코드에서 처리해야 합니다.

```ts title="db/config.ts" {8}
import { defineTable, column } from 'astro:db';

// 테이블을 정의합니다.
const UserTable = defineTable({
	columns: {
		id: column.number({ primaryKey: true }),
		name: column.text(),
    rank: column.text({ enum: ['user', 'mod', 'admin'] }),
	},
});

// 결과 타입을 정의합니다.
type UserTableInferInsert = {
    id?: string;
    name: string;
    rank: "user" | "mod" | "admin";
}
```

### `indexes`

<p>

**타입:** `{ on: string | string[]; unique?: boolean | undefined; name?: string | undefined; }[]`
</p>

테이블 인덱스는 특정 열 또는 열 조합에 대한 조회 속도를 향상시키는 데 사용됩니다. `indexes` 속성은 인덱스를 생성할 열을 지정하는 구성 객체의 배열을 값으로 전달받습니다.

```ts title="db/config.ts" {9-11}
import { defineTable, column } from 'astro:db';

const Comment = defineTable({
  columns: {
    authorId: column.number(),
    published: column.date(),
    body: column.text(),
  },
  indexes: [
    { on: ["authorId", "published"], unique: true },
  ]
});
```

그러면 `authorId` 및 `published` 열에 `Comment_authorId_published_idx`라는 이름의 고유 인덱스가 생성됩니다.

각 인덱스에 대해 다음 구성 옵션을 사용할 수 있습니다.

- `on` - 인덱싱할 단일 열 또는 열 이름 배열입니다.
- `unique` (선택 사항) - 인덱스가 생성된 열 전체에 고유한 값을 적용하려면 `true`로 설정합니다.
- `name` (선택 사항) - 고유 인덱스의 사용자 정의 이름입니다. 이는 색인화되는 테이블 및 열 이름을 기반으로 Astro에서 생성된 이름을 재정의합니다 (예: `Comment_authorId_published_idx`). 사용자 정의 이름은 전역적이므로 인덱스 이름이 테이블 간에 충돌하지 않는지 확인하세요.

### `foreignKeys`

<p>

**타입:** `{ columns: string | string[]; references: () => Column | Column[]; }[]`
</p>

:::tip

`foreignKeys`는 여러 테이블 열을 연결하기 위한 고급 API입니다. 단일 열만 참조해야 하는 경우 [열 `references` 속성](#columns)을 사용하세요.

:::

외래 키는 두 테이블 간 관계를 설정하는 데 사용됩니다. `foreignKeys` 속성은 테이블 간 하나 이상의 열을 연결할 수 있는 구성 객체의 배열을 허용합니다.

```ts title="db/config.ts" {12-20}
import { defineTable, column } from 'astro:db';

const Author = defineTable({
  columns: {
    firstName: column.text(),
    lastName: column.text(),
  },
});

const Comment = defineTable({
  columns: {
    authorFirstName: column.text(),
    authorLastName: column.text(),
    body: column.text(),
  },
  foreignKeys: [
    {
      columns: ["authorFirstName", "authorLastName"],
      references: () => [Author.columns.firstName, Author.columns.lastName],
    },
  ],
});
```

각 외래 키 구성 객체는 다음 속성을 허용합니다.

- `columns` - 참조된 테이블과 관련된 단일 열 또는 열 이름의 배열입니다.
- `references` - 참조된 테이블에서 단일 열 또는 열 배열을 반환하는 함수입니다.

## Astro DB CLI 참조

Astro DB에는 로컬 및 libSQL 호환 데이터베이스와 상호 작용하는 CLI 명령 세트가 포함되어 있습니다.

이러한 명령은 GitHub CI action을 사용할 때 자동으로 호출되며 `astro db` CLI를 사용하여 수동으로 호출할 수 있습니다.

### `astro db push`

**플래그:**

- `--force-reset` 주요 스키마 변경이 필요한 경우 모든 프로덕션 데이터를 재설정합니다.

데이터베이스 구성 변경 사항을 프로젝트 데이터베이스에 안전하게 푸시합니다. 그러면 데이터 손실 위험이 있는지 확인하고 권장되는 마이그레이션 단계를 안내합니다. 주요 스키마 변경을 수행해야 하는 경우 `--force-reset` 플래그를 사용하여 모든 프로덕션 데이터를 재설정하세요.

### `astro db verify`

로컬 데이터베이스 구성과 원격 데이터베이스 구성 간 차이점을 확인합니다. 이는 `astro db push`에 의해 자동으로 실행됩니다. `verify`는 로컬 `db/config.ts` 파일을 원격 데이터베이스와 비교하고 변경 사항이 감지되면 경고합니다.

### `astro db execute <file-path>`

**플래그:**

- `--remote` libSQL 호환 데이터베이스에 대해 실행하세요. 개발 서버에 대한 실행을 생략합니다.

데이터베이스를 읽거나 쓰려면 `.ts` 또는 `.js` 파일을 실행하세요. 이는 파일 경로를 인수로 받아들이고 `astro:db` 모듈을 사용하여 타입 안정성을 갖춘 쿼리를 작성할 수 있도록 지원합니다. libSQL 호환 데이터베이스에 대해 실행하려면 `--remote` 플래그를 사용하고, 개발 서버에 대해 실행하려면 플래그를 생략하세요. [개발 데이터를 시드](/ko/guides/astro-db/#개발-모드에서-데이터베이스-시드)하는 방법에 대한 예시 파일을 참조하세요.

### `astro db shell --query <sql-string>`

**플래그:**

- `--query` 실행할 원시 SQL 쿼리입니다.
- `--remote` libSQL 호환 데이터베이스에 대해 실행하세요. 개발 서버에 대한 실행을 생략합니다.

데이터베이스에 대해 원시 SQL 쿼리를 실행합니다. libSQL 호환 데이터베이스에 대해 실행하려면 `--remote` 플래그를 사용하고, 개발 서버에 대해 실행하려면 플래그를 생략하세요.

## Astro DB 유틸리티 참조

### `isDbError()`

<p>

**타입:** `(err: unknown) => boolean`<br />
<Since v="0.9.1" pkg="@astrojs/db" />
</p>

`isDbError()` 함수는 오류가 libSQL 데이터베이스 예외인지 확인합니다. 여기에는 참조 사용 시 외래 키 제약 조건 오류가 포함되거나 데이터 삽입 시 필드 누락이 포함될 수 있습니다. `isDbError()`를 try / catch 블록과 결합하여 애플리케이션의 데이터베이스 오류를 처리할 수 있습니다.

```ts title="src/pages/api/comment/[id].ts" "idDbError"
import { db, Comment, isDbError } from 'astro:db';
import type { APIRoute } from 'astro';

export const POST: APIRoute = (ctx) => {
  try {
    await db.insert(Comment).values({
      id: ctx.params.id,
      content: 'Hello, world!'
    });
  } catch (e) {
    if (isDbError(e)) {
      return new Response(`Cannot insert comment with id ${id}\n\n${e.message}`, { status: 400 });
    }
    return new Response('An unexpected error occurred', { status: 500 });
  }

  return new Response(null, { status: 201 });
};
```
